package se.chalmers.tda366.crumble.core.impl;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import se.chalmers.tda366.crumble.core.ICategory;
import se.chalmers.tda366.crumble.core.IModel;
import se.chalmers.tda366.crumble.utils.IObservable;




/**
 * Representing the Model
 * @author hajo
 *
 */
public class Model implements IModel, IObservable {

	// Java Beans style
	private final PropertyChangeSupport observers = new PropertyChangeSupport(
			this);

	// This is a singleton
	private static IModel instance = null;
	
	private ArrayList<ICategory> categories;
	
	private Model() {
		categories = new ArrayList<ICategory>();
	}

	public static IModel getInstance() {
		if (instance == null) {
			instance = new Model();
		}
		return instance;
	}
	
	public static IObservable getInstanceAsObservable() {
		return (IObservable) getInstance();
	}

	// IObservable -------------------------------------
	
	@Override
	public void addPropertyChangeListener(PropertyChangeListener observer) {
		observers.addPropertyChangeListener(observer);
	}

	@Override
	public void removePropertyChangeListener(PropertyChangeListener observer) {
		observers.removePropertyChangeListener(observer);
	}

	@Override
	public void addCategory(ICategory category) {
		categories.add(category);
	}

	@Override
	public List<ICategory> getCategories() {
		return categories;
	}

	@Override
	public void loadModel() {
		try {
            InputStream file = new FileInputStream(new File(System.getProperty("user.home") + "/.crumbleApp/user_feeds.crum"));
            InputStream buffer = new BufferedInputStream(file);
            ObjectInput input = new ObjectInputStream(buffer);

            try {
                categories = (ArrayList<ICategory>)input.readObject();
            }
            finally {
                input.close();
            }
        }
        catch (ClassNotFoundException e) {
            System.err.println("ClassNotFoundException!");
        }
        catch (IOException e) {
            System.err.println("Unable to load feeds!");
        }
	}

	@Override
	public void saveModel() {
		//Remove JPanels from category before saving to disc. Issue ID 2, "Saving feeds on system close crashes"
		for(ICategory category : categories)
		{
			category.setPanel(null);
		}
		
		//Try to save the feeds to disc.
		try {
			new File(System.getProperty("user.home") + "/.crumbleApp/").mkdir();
            OutputStream file = new FileOutputStream(new File(System.getProperty("user.home") + "/.crumbleApp/user_feeds.crum"));
            OutputStream buffer = new BufferedOutputStream(file);
            ObjectOutput output = new ObjectOutputStream(buffer);

            try {
                output.writeObject(categories);
            }
            finally {
                output.close();
            }
        }
        catch (IOException e) {
            System.err.println("Unable to save feeds.");
        }
	}

	@Override
	public void removeCategory(ICategory category) {
		categories.remove(category);
	}

}
